<?php
/**
 * User.php
 * 用户接口
 * @author Deepseath
 * @version $Id$
 */
namespace deepseath\xinrenxinshi\Api;

use deepseath\xinrenxinshi\Xinrenxinshi;

class User
{
    /**
     * 基类服务对象
     * @var \deepseath\xinrenxinshi\Xinrenxinshi
     */
    protected $service = null;

    /**
     * 分组类型：1-合同记录
     * @var string
     */
    const GROUP_TYPE_CONTRACT = '1';
    /**
     * 分组类型：5-兼职信息
     * @var string
     */
    const GROUP_TYPE_PTJ = '5';
    /**
     * 分组类型：7-教育经历
     * @var string
     */
    const GROUP_TYPE_EDU = '7';
    /**
     * 分组类型：8-工作经历
     * @var string
     */
    const GROUP_TYPE_WORK = '8';
    /**
     * 分组类型：9-培训经历
     * @var string
     */
    const GROUP_TYPE_TRAINING = '9';
    /**
     * 分组类型：10-证书记录
     * @var string
     */
    const GROUP_TYPE_CERT = '10';
    /**
     * 分组类型：11-联系人记录
     * @var string
     */
    const GROUP_TYPE_CONTACT = '11';

    /**
     * 员工状态：在职员工
     * @var integer
     */
    const STATUS_ON = 0;
    /**
     * 员工状态：离职员工
     * @var integer
     */
    const STATUS_OFFLINE = 1;
    /**
     * 员工状态：待入职
     * @var integer
     */
    const STATUS_WAIT = 2;
    /**
     * 员工状态：删除
     * @var integer
     */
    const STATUS_DEL = 8;

    private $_detailList = [];
    private $_simpleList = [];

    public function __construct(Xinrenxinshi $service)
    {
        $this->service = $service;
    }

    /**
     * 列出所有分组类型 id
     *
     * @return array
     */
    public function groupNameList() : array
    {
        return [
            self::GROUP_TYPE_CONTRACT,
            self::GROUP_TYPE_PTJ,
            self::GROUP_TYPE_EDU,
            self::GROUP_TYPE_WORK,
            self::GROUP_TYPE_TRAINING,
            self::GROUP_TYPE_CERT,
            self::GROUP_TYPE_CONTACT
        ];
    }

    /**
     * 1.5.5 员工基础列表
     * @desc 查询员工基础信息的列表,主要包含员工的id，姓名，手机号，入职日期，聘用形式以及员工状态等基本信息。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/basisInfo_v5.html
     * @param array $params
     * <pre>
     *   pageNo	Integer	Y	起始页码，默认从0开始，翻页+1
     *   pageSize	Integer	Y	查询员工数量，单次数量限制100
     *   fetchChild	Integer	Y	是否包含子部门员工,0不包含,1包含
     *   departmentId	String	N	部门ID,不传表示全部部门员工
     *   status	Integer	N	员工状态，默认为0。0:在职员工、1:离职员工、2:待入职、8:删除
     *   modtime	Integer	N	更新时间(精确到秒)，员工基础列表的增量查询。如果传了该参数，则只返回更新时间在查询时间之后的员工数据
     * </pre>
     * @return array
     */
    public function simpleList(array $params = []) : array
    {
        if (empty($params) && $this->_simpleList) {
            return $this->_simpleList;
        }
        $params = array_merge([
            'pageNo' => 0,
            'pageSize' => 100,
            'fetchChild' => 1,
            'departmentId' => '',
            'status' => self::STATUS_ON,
            'modtime' => 0
        ], $params);

        $result = $this->_simpleList = $this->service->apiPostMulti('/employee/simplelist', $params);
        if (empty($params)) {
            $this->_simpleList = $result;
        }

        return $result;
    }

    /**
     * 1.5.6 员工详情列表
     * @desc 查询员工详细信息的列表。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/detailList_v5.html
     * @param array $params
     * <pre>
     *  departmentId String	N	部门ID，不为空时获取指定部门下的员工，为空时默认获取公司全部的员工
     *  pageNo      Integer	Y	起始页码，默认从0开始，翻页+1
     *  pageSize    Integer	Y	查询员工数量，单次数量限制100
     *  fetchChild  Integer	Y	是否包含子部门员工,0不包含,1包含
     *  status      Integer	Y	员工状态，默认为0。0:在职员工、1:离职员工、2:待入职、8:删除
     *  modtime     Integer	N	更新时间(精确到秒)，员工详情列表的增量查询。如果传了该参数，则只返回更新时间在查询时间之后的员工数据
     * </pre>
     * @return array
     */
    public function detailList(array $params = []) : array
    {
        if (empty($params) && $this->_detailList) {
            return $this->_detailList;
        }
        $params = array_merge([
            'departmentId' => '',
            'pageNo' => 0,
            'pageSize' => 100,
            'fetchChild' => 1,
            'status' => 0,
            'modtime' => 0,
        ], $params);
        $result = $this->service->apiPostMulti('/employee/list', $params);
        if (empty($params)) {
            $this->_detailList = $result;
        }

        return $result;
    }

    /**
     * 1.5.7 员工详情信息
     * @desc 根据员工id获取员工的详细信息。可以通过此接口获取员工的基本信息，账号信息，通讯信息 自定义信息，岗位信息等字段信息。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/info_v5.html
     * @param array $params
     * <pre>
     *  employeeId	String	Y	员工id
     *  status	Integer	N	员工状态，默认为0。0:在职员工、1:离职员工、2:待入职、8:删除
     * </pre>
     * @return array
     */
    public function detail(array $params) : array
    {
        $params = array_merge([
            'employeeId' => '',
            'status' => self::STATUS_ON
        ], $params);

        return $this->service->apiPost('/employee/detail', $params);
    }

    /**
     * 1.5.8 查询员工id
     * @desc 通过手机号，邮箱，工号等来查询员工id
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/getEmployeeID_v5.html
     * @param array $params
     * <pre>
     *  type	String	Y	参数类型，0-手机号，1-工作邮箱，2-工号，例如选0类型，则只能用mobiles列表进行查询
     *  mobiles	List<String>	N	要查询的员工手机号，最多100条
     *  emails	List<String>	N	要查询的员工工作邮箱，最多100条
     *  jobNumbers	List<String>	N	要查询的员工工号，最多100条
     *  status	Integer	N	默认是在职状态，0-在职，1-离职，2-待入职
     * </pre>
     * @throws \Exception
     * @return array
     */
    public function getId(array $params) : array
    {
        if (!isset($params['type'])) {
            throw new \Exception('xinrenxinshi SDK：查询“参数类型(type)”必须指定');
        }
        switch ($params['type']) {
            case 0:
                // 使用手机号查询
                if (!isset($params['mobiles']) || !is_array($params['mobiles'])) {
                    throw new \Exception('xinrenxinshi SDK: 手机号列表必须提供');
                }
            break;
            case 1:
                // 使用工作邮箱查询
                if (!isset($params['mobiles']) || !is_array($params['mobiles'])) {
                    throw new \Exception('xinrenxinshi SDK: 工作邮箱列表必须提供');
                }
            break;
            case 2:
                // 使用工号查询
                if (!isset($params['mobiles']) || !is_array($params['mobiles'])) {
                    throw new \Exception('xinrenxinshi SDK: 工号列表必须提供');
                }
            break;
            default:
                // 未知的查询类型
                throw new \Exception('xinrenxinshi SDK: 为止的查询类型');
            break;
        }

        $params = array_merge([
            'status' => self::STATUS_ON
        ], $params);

        return $this->service->apiPost('/employee/getId', $params);
    }

    /**
     * 1.5.11 员工成长记录
     * @desc 查询员工的成长记录.返回记录的时间，记录类型以及具体的操作内容。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/career_v5.html
     * @param array $params
     * <pre>
     *  employeeIds	List<String>	Y	员工id列表，单次支持100个员工。支持在职和离职员工查询
     * </pre>
     * @return array
     */
    public function careers(array $params) : array
    {
        $params = array_merge([
            'employeeIds' => []
        ], $params);

        return $this->service->apiPost('/employee/careers', $params);
    }

    /**
     * 1.5.13 员工文件下载
     * @desc 根据员工id和文件key下载该员工之前上传的文件。员工详情接口中返回的图片类型的字段都是文件key，
     *          可以通过此接口来获取实际的图片信息。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/download_v5.html
     * @param array $params
     * <pre>
     *  employeeId	String	Y	员工id
     *  fileKey	String	Y	文件key
     * </pre>
     * @return array
     * <pre>
     *  正常下载时，消息体为文件流，相应头为对应的文件相关信息
     *  获取文件失败时，contentType为application/json，具体返回体说明如下：
     * </pre>
     */
    public function download(array $params) : array
    {
        $params = array_merge([
            'employeeId' => '',
            'fileKey' => ''
        ], $params);

        return $this->service->apiPost('/employee/file/download', $params);
    }

    /**
     * 1.5.14 员工预离职列表
     * @desc 查询公司内所有预离职的员工
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/preDismiss_v5.html
     * @return array
     */
    public function predismissList() : array
    {
        return $this->service->apiPost('/employee/predismiss/list', []);
    }

    /**
     * 1.14.1 【历史接口】员工固定分组信息字段查询
     * @desc 用于获取分组信息对应的字段信息，包含字段ID、字段名称、是否必须字段、下拉列表字段信息等信息。主要是用于后面员工分组字段信息的 添加或者更新。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/group/fields_v5.html
     * @param array $params
     * @return array
     */
    public function groupFields(array $params = []) : array
    {
        $params = array_merge([
            // 分组类型
            'groupType' => self::GROUP_TYPE_CONTRACT,
        ], $params);

        return $this->service->apiPost('/employee/group/fields', $params);
    }

    /**
     * 1.14.2 【历史接口】员工分组信息批量查询
     * @desc 批量查询多个员工的分组信息。包含当前分组信息是否能编辑等信息；有些分组信息是不允许编辑更新的，例如：电子合同信息。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/group/list_v5.html
     * @param array $params
     * <pre>
     *  employeeIds	Lits<String>	Y	员工id列表，员工id个数限制在1～100之间
     *  employeeStatus	Integer	N	员工状态，默认为0。0:在职员工、1:离职员工、2:待入职、8:删除
     *  groupType	String	Y	分组类型，1-合同记录,5-兼职信息,7-教育经历,8-工作经历,9-培训经历,10-证书记录,11-联系人记录
     * </pre>
     * @return array
     */
    public function groupList(array $params) : array
    {
        $params = array_merge([
            'employeeIds' => [],
            'employeeStatus' => self::STATUS_ON,
            'groupType' => self::GROUP_TYPE_CONTRACT
        ], $params);

        return $this->service->apiPost('/employee/group/list', $params);
    }

    /**
     * 1.5.20 员工文件下载地址
     * @desc 根据员工id和文件key下载该员工之前上传的文件。员工详情接口中返回的图片类型的字段都是文件key，可以通过此接口来获取实际的图片的下载链接。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/downloadurl_v5.html
     * @param array $params
     * <pre>
     *  employeeId	String	Y	员工id
     *  fileKey	String	Y	文件key
     * </pre>
     * @return array
     */
    public function getDownloadUrl(array $params) : array
    {
        $params = array_merge([
            'employeeId' => '',
            'fileKey' => ''
        ], $params);

        return $this->service->apiPost('/employee/file/getdownloadurl', $params);
    }

    /**
     * 1.5.5.1 根据指定员工 ID 找到员工基本信息列表
     * @param array $employIds
     * @return array
     */
    public function ddListById(array $employIds) : array
    {
        static $list = null;
        if ($list === null) {
            $list = $this->simpleList();
        }
        $result = [];
        foreach ($list as $e) {
            if (!in_array($e['employeeId'], $employIds)) {
                $result[$e['employeeId']] = $e;
            }
        }

        return $result;
    }

    /**
     * 获取指定成员的指定分组字段数据
     * @desc 如不指定成员则获取全部成员，如不指定分组字段类型，则默认获取合同记录和教育经历数据，注意：如果获取成员较多本方法执行时间会比较长
     * @param array $employeeIds
     * @param array $groupTypes
     * @param int $employeeStatus
     * @return array
     */
    public function ddGroupDetailList(array $employeeIds = [], array $groupTypes = [], int $employeeStatus = 0) : array
    {
        if (empty($employeeIds)) {
            $employeeIds = array_column($this->simpleList(['status' => $employeeStatus]), 'employeeId');
        }

        // 获取员工 ID 分批次
        $userGroups = [];
        $userTotals = count($employeeIds);
        $userPerpage = 100;
        $userPages = ceil($userTotals / $userPerpage);
        for ($i = 0; $i < $userPages; $i++) {
            $userGroups[] = array_slice($employeeIds, $i * $userPerpage, $userPerpage);
        }

        if (empty($groupTypes)) {
            // 默认只获取：合同和教育经历两个分组数据
            $groupTypes = [self::GROUP_TYPE_CONTRACT, self::GROUP_TYPE_EDU];
        }

        $result = [];
        foreach ($userGroups as $_employeeIds) {
            foreach ($groupTypes as $_groupType) {
                $r = $this->groupList(['employeeIds' => $_employeeIds, 'employeeStatus' => $employeeStatus, 'groupType' => $_groupType]);
                foreach ($r as $_rData) {
                    $result[$_rData['employeeId']][$_groupType] = $this->ddFormatGroupInfo($_rData);
                }
                unset($_rData);
            }
            unset($_groupType);
        }

        return $result;
    }

    /**
     * 格式化分组信息字段数据
     * @param array $data
     * @return array
     */
    public function ddFormatGroupInfo(array $data)
    {
        $result = [];
        foreach ($data['recordDataList'] as $key => $values) {
            $tmp = [];
            foreach ($values['fields'] as $vv) {
                $tmp[$vv['fieldIdName']] = [
                    'value' => $vv['fieldValue'],
                    'valueName' => $vv['fieldValueName']
                ];
            }
            $result[$key] = $tmp;
            unset($tmp, $vv);
        }

        return $result;
    }

    /**
     * 1.5.16 获取所有分组
     * @desc 获取所有员工字段分组，包括固定分组和自定义分组。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/group/groupInfo_v5.html
     * @return array
     */
    public function groupInfo() : array
    {
        return $this->service->apiPost('/employee/group/info', []);
    }

    /**
     * 1.5.18 获取员工分组的字段值
     * @desc 查询员工分组的所有字段数据，包括自定义字段和固定字段。包含当前分组信息是否能编辑等信息；有些分组信息是不允许编辑更新的，例如：电子合同信息。
     * @see https://api.xinrenxinshi.com/doc/v3/page/employee/group/employeeFieldInfo_v5.html
     * @param array $params
     * <pre>
     *  employeeIds array   Y   员工id列表，员工id个数限制在1～100之间
     *  groupId     String  Y   分组id
     *  status      Integer N   员工状态，默认为0。0:在职员工、1:离职员工、2:待入职、8:删除
     *  hasDel      Integer N   是否查删除状态的分组字段记录，0否1是，默认为0
     * </pre>
     * @return array
     */
    public function groupFieldValues(array $params = []) : array
    {
        $params = array_merge([
            'employeeIds' => [],
            'employeeStatus' => self::STATUS_ON,
            'groupType' => self::GROUP_TYPE_CONTRACT
        ], $params);

        return $this->service->apiPost('/employee/group/list', $params);
    }
}
